import json
from pathlib import Path
import datetime
from io import BytesIO

from django.db import models
from django.shortcuts import render
from django.views.generic import ListView,CreateView,UpdateView,DeleteView
from django.http import HttpResponse, JsonResponse
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password
from django.urls import reverse_lazy

import openpyxl

from .models import Student
from .forms import StudentForm
from utils.handle_excel import ReadExcel
from grades.models import Grade

# Create your views here.


class StudentListView(ListView):
    model = Student
    template_name = 'students/student_list.html'
    context_object_name = 'students'
    paginate_by = 10

    def get_queryset(self):
        queryset = super().get_queryset()
        grade_id = self.request.GET.get('grade')
        search = self.request.GET.get('search')
        
        if grade_id:
            queryset = queryset.filter(grade__pk=grade_id)
            
        if search:
            queryset = queryset.filter(
                models.Q(student_name=search) |
                models.Q(student_number=search)
            )
        # 外键关系访问Grade模型的grade_number字段
        queryset = queryset.order_by('grade__grade_number', 'student_number')
        return queryset

    def get_context_data(self):
        context = super().get_context_data()
        # 获取所有班级并添加到上下文
        context['grades'] = Grade.objects.all().order_by('grade_number')
        context['current_grade'] = self.request.GET.get('grade', '') # int(self.request.GET.get('grade', 0))
        # context['search'] = self.request.GET.get('search', '')  
        return context

class StudentCreateView(CreateView):
    model = Student
    template_name = 'students/student_form.html'  # Specify your template name
    form_class = StudentForm  # Use a form class to handle student creation
    # success_url = '/students/'  # Redirect to the student list after successful creation

    def form_valid(self, form):
        # 表单字段验证成功
        # 接受字段
        student_name = form.cleaned_data.get('student_name')
        student_number = form.cleaned_data.get('student_number')
        # 写入到auth_user表
        username = student_name + '_' +student_number
        password = student_number[-6:]

        # 获取所有关于User的username记录
        users = User.objects.filter(username=username)

        # 判断用户是否存在
        if users.exists():
            user = users.first()
        else:
            # 创建auth_user记录
            user = User.objects.create_user(username=username,password=password)
        
        # 先设置user关联再保存表单
        form.instance.user = user
        # response = super().form_valid(form)
        form.save()

        # 返回json响应
        return JsonResponse({
            'status': 'success',
            'message': '学生信息创建成功',
            # 'redirect_url': self.get_success_url()
        }, status=200)
    
    def form_invalid(self, form):
        errors = form.errors.as_json() #获取所有错误信息
        return JsonResponse({'status': 'error','messages':errors,}, status=400)
        # 验证失败
    
class StudentUpdateView(UpdateView):
    model = Student
    template_name = 'students/student_form.html'
    form_class = StudentForm

    def form_valid(self,form):
        # 获取学生对象是咧
        student = form.save(commit=False)
        # 检查一下是否修改了student_name和student_number  只要修改了数据就会在changed_data里
        if 'student_name' or 'student_number' in form.changed_data:
            student.user.username = form.cleaned_data.get('student_name') + '_' + form.cleaned_data.get('student_number')
            student.user.password = make_password(form.cleaned_data.get('student_number')[-6:])
            student.user.save() # 保存更改的用户模型

        # 保存student模型
        student.save()

        # 返回json响应
        return JsonResponse({
            'status': 'success',
            'message': '信息修改成功',
            # 'redirect_url': self.get_success_url()
        }, status=200)        


    def form_invalid(self, form):
        errors = form.errors.as_json() #获取所有错误信息
        return JsonResponse({
            'status': 'error',
            'messages':errors,
        }, status=400)
    
class StudentDeleteView(DeleteView):
    model = Student
    success_url = reverse_lazy('student_list')

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        try:
            self.object.delete()
            return JsonResponse({
                'status':'success',
                'messages':'删除成功',
            },status=200)
        except Exception as e:
            return JsonResponse({
            'status': 'error',
            'messages':'删除失败' + str(e)
        },status=400)


class StudentBulkDelteView(DeleteView):
    model = Student
    success_url = reverse_lazy('student_list')

    def post(self, request, *args, **kwargs):
        selected_ids = request.POST.getlist('student_ids')
        if not selected_ids:
            return JsonResponse({'status':'error','messages':'请选择要删除的学生',}, status=400)
        
        self.object_list = self.get_queryset().filter(id__in=selected_ids)
        try:
            self.object_list.delete()
            return JsonResponse({'status':'success','messages':'删除成功',}, status=200)
        except Exception as e:
            return 
        
def upload_student(request):
    """上传学生信息"""
    if request.method == 'POST':
        file = request.FILES['excel_file']

        if not file:
            return JsonResponse({'status': 'error','messages': '请上传excel文件',}, status=400)
        
        ext = Path(file.name).suffix 
        if ext.lower() != '.xlsx':
            return JsonResponse({
                'status': 'error',
                'messages': '文件类型错误，请上传.xlsx格式的文件',
            }, status=400)

        # openpyxl 读取excel文件内容
        read_excel = ReadExcel(file)
        data = read_excel.get_data()
        if data[0] !=  ['姓名','学号','班级','性别','生日','联系方式','地址']:
            return JsonResponse({
                'status': 'error',
                'messages': '信息内容有误',
            }, status=400)

        # 写入到数据库
        for row in data[1:]:
            student_name, student_number, grade, gender, birthday, contact, address = row
            grade = Grade.objects.filter(grade_name=grade).first()
            if not grade:
                return JsonResponse({
                    'status': 'error',
                    'messages': f'{grade}不存在',
                }, status=400)
            
            if not student_name:
                return JsonResponse({'status':'error', 'messages':'学生姓名不为空'}, status=400)
            if not student_number or len(str(student_number)) != 9:
                return JsonResponse({'status':'error', 'messages':'学籍号必须为9位'}, status=400)
            # 检查生日格式是否错误
            if not isinstance(birthday, datetime.datetime):
                return JsonResponse({'status':'error', 'messages':'生日格式错误'}, status=400)
            # 检查学生是否存在
            if Student.objects.filter(student_number=student_number).exists():
                return JsonResponse({'status':'error', 'messages':f'{student_number}已存在'}, status=400)

            try:
                username = student_name + '_' + str(student_number)
                users = User.objects.filter(username=username)
                if users.exists():
                    user = users.first()
                else:
                    password = str(student_number)[-6:]
                    user = User.objects.create_user(username=username,password=password)

                Student.objects.create(
                    student_name = student_name,
                    student_number = student_number,
                    grade = grade,
                    gender = '男' if gender == '男' else '女',
                    birthday = birthday,
                    contact = contact,
                    address = address,
                    user = user,
                )
            except Exception as e:
                return JsonResponse({'status':'error', 'messages':f'上传失败{e}'}, status=500)
            
        return JsonResponse({'status':'success', 'messages':'上传成功'}, status=200)

def export_excel(request):
    if request.method == "POST":
        data = json.loads(request.body)
        grade_id = data.get('grade')
        # 判断grade_id是否存在
        if not grade_id:
            return JsonResponse({'status':'error','messages':'班级参数缺失'}, status=400)
        
        # 判断班级是否存在
        try:
            grade = Grade.objects.get(id=grade_id)
        except Grade.DoesNotExist:
            return JsonResponse({'status':'error','messages':'班级不存在'}, status=404)
        
        # 从数据库查询学生数据
        students = Student.objects.filter(grade=grade)
        if not students.exists():
            return JsonResponse({'status':'error', 'messages':'找不到指定班级的学生信息'}, status=404)
        
        # 操作excel
        wb = openpyxl.Workbook()
        ws = wb.active
        # 添加表头
        columns = ['姓名','学号','班级','性别','生日','联系方式','地址']
        ws.append(columns)

        for student in students:
            ws.append([student.student_name, student.student_number, student.grade.grade_name, student.gender, student.birthday, student.contact, student.address])

        # 将excel数据保存到内存中
        excel_file = BytesIO()
        wb.save(excel_file)
        wb.close()

        # 
        excel_file.seek(0)

        # 
        response = HttpResponse(excel_file.read(), content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
        response['Content-Disposition'] = 'attachment; filename="student.xlsx"'
        return response
